﻿using System;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
using Mono.Collections.Generic;
using Mono.Security.Cryptography;


namespace Mono.Cecil
{
    internal static class Mixin
    {
        public enum Argument
        {
            name,
            fileName,
            fullName,
            stream,
            type,
            method,
            field,
            parameters,
            module,
            modifierType,
            eventType,
            fieldType,
            declaringType,
            returnType,
            propertyType,
            interfaceType,
            constraintType
        }

        public const int TableCount = 58;

        public const int CodedIndexCount = 14;

        public static Version ZeroVersion = new Version(0, 0, 0, 0);

        public const int NotResolvedMarker = -2;

        public const int NoDataMarker = -1;

        internal static object NoValue = new object();

        internal static object NotResolved = new object();

        public const string mscorlib = "mscorlib";

        public const string system_runtime = "System.Runtime";

        public const string system_private_corelib = "System.Private.CoreLib";

        public const string netstandard = "netstandard";

        public static ImageDebugHeaderEntry GetCodeViewEntry(this ImageDebugHeader header)
        {
            return header.GetEntry(ImageDebugType.CodeView);
        }

        public static ImageDebugHeaderEntry GetDeterministicEntry(this ImageDebugHeader header)
        {
            return header.GetEntry(ImageDebugType.Deterministic);
        }

        public static ImageDebugHeader AddDeterministicEntry(this ImageDebugHeader header)
        {
            ImageDebugDirectory directory = default(ImageDebugDirectory);
            directory.Type = ImageDebugType.Deterministic;
            ImageDebugHeaderEntry imageDebugHeaderEntry = new ImageDebugHeaderEntry(directory, Empty<byte>.Array);
            if (header == null)
            {
                return new ImageDebugHeader(imageDebugHeaderEntry);
            }

            ImageDebugHeaderEntry[] array = new ImageDebugHeaderEntry[header.Entries.Length + 1];
            Array.Copy(header.Entries, array, header.Entries.Length);
            array[^1] = imageDebugHeaderEntry;
            return new ImageDebugHeader(array);
        }

        public static ImageDebugHeaderEntry GetEmbeddedPortablePdbEntry(this ImageDebugHeader header)
        {
            return header.GetEntry(ImageDebugType.EmbeddedPortablePdb);
        }

        public static ImageDebugHeaderEntry GetPdbChecksumEntry(this ImageDebugHeader header)
        {
            return header.GetEntry(ImageDebugType.PdbChecksum);
        }

        private static ImageDebugHeaderEntry GetEntry(this ImageDebugHeader header, ImageDebugType type)
        {
            if (!header.HasEntries)
            {
                return null;
            }

            for (int i = 0; i < header.Entries.Length; i++)
            {
                ImageDebugHeaderEntry imageDebugHeaderEntry = header.Entries[i];
                if (imageDebugHeaderEntry.Directory.Type == type)
                {
                    return imageDebugHeaderEntry;
                }
            }

            return null;
        }

        public static string GetPdbFileName(string assemblyFileName)
        {
            return Path.ChangeExtension(assemblyFileName, ".pdb");
        }

        public static string GetMdbFileName(string assemblyFileName)
        {
            return assemblyFileName + ".mdb";
        }

        public static bool IsPortablePdb(string fileName)
        {
            using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                return IsPortablePdb(stream);
            }
        }

        public static bool IsPortablePdb(Stream stream)
        {
            if (stream.Length < 4)
            {
                return false;
            }

            long position = stream.Position;
            try
            {
                BinaryReader binaryReader = new BinaryReader(stream);
                return binaryReader.ReadUInt32() == 1112167234;
            }
            finally
            {
                stream.Position = position;
            }
        }

        public static uint ReadCompressedUInt32(this byte[] data, ref int position)
        {
            uint result;
            if ((data[position] & 0x80) == 0)
            {
                result = data[position];
                position++;
            }
            else if ((data[position] & 0x40) == 0)
            {
                result = (uint)((data[position] & -129) << 8);
                result |= data[position + 1];
                position += 2;
            }
            else
            {
                result = (uint)((data[position] & -193) << 24);
                result |= (uint)(data[position + 1] << 16);
                result |= (uint)(data[position + 2] << 8);
                result |= data[position + 3];
                position += 4;
            }

            return result;
        }

        public static MetadataToken GetMetadataToken(this CodedIndex self, uint data)
        {
            uint rid;
            TokenType type;
            switch (self)
            {
                case CodedIndex.TypeDefOrRef:
                    rid = data >> 2;
                    switch (data & 3)
                    {
                        case 0u:
                            break;
                        case 1u:
                            goto IL_0075;
                        case 2u:
                            goto IL_0080;
                        default:
                            goto end_IL_0006;
                    }

                    type = TokenType.TypeDef;
                    goto IL_0644;
                case CodedIndex.HasConstant:
                    rid = data >> 2;
                    switch (data & 3)
                    {
                        case 0u:
                            break;
                        case 1u:
                            goto IL_00bd;
                        case 2u:
                            goto IL_00c8;
                        default:
                            goto end_IL_0006;
                    }

                    type = TokenType.Field;
                    goto IL_0644;
                case CodedIndex.HasCustomAttribute:
                    rid = data >> 5;
                    switch (data & 0x1F)
                    {
                        case 0u:
                            break;
                        case 1u:
                            goto IL_0155;
                        case 2u:
                            goto IL_0160;
                        case 3u:
                            goto IL_016b;
                        case 4u:
                            goto IL_0176;
                        case 5u:
                            goto IL_0181;
                        case 6u:
                            goto IL_018c;
                        case 7u:
                            goto IL_0197;
                        case 8u:
                            goto IL_019e;
                        case 9u:
                            goto IL_01a9;
                        case 10u:
                            goto IL_01b4;
                        case 11u:
                            goto IL_01bf;
                        case 12u:
                            goto IL_01ca;
                        case 13u:
                            goto IL_01d5;
                        case 14u:
                            goto IL_01e0;
                        case 15u:
                            goto IL_01eb;
                        case 16u:
                            goto IL_01f6;
                        case 17u:
                            goto IL_0201;
                        case 18u:
                            goto IL_020c;
                        case 19u:
                            goto IL_0217;
                        case 20u:
                            goto IL_0222;
                        case 21u:
                            goto IL_022d;
                        default:
                            goto end_IL_0006;
                    }

                    type = TokenType.Method;
                    goto IL_0644;
                case CodedIndex.HasFieldMarshal:
                    {
                        rid = data >> 1;
                        uint num11 = data & 1;
                        uint num12 = num11;
                        if (num12 != 0)
                        {
                            if (num12 != 1)
                            {
                                break;
                            }

                            type = TokenType.Param;
                        }
                        else
                        {
                            type = TokenType.Field;
                        }

                        goto IL_0644;
                    }
                case CodedIndex.HasDeclSecurity:
                    rid = data >> 2;
                    switch (data & 3)
                    {
                        case 0u:
                            break;
                        case 1u:
                            goto IL_029f;
                        case 2u:
                            goto IL_02aa;
                        default:
                            goto end_IL_0006;
                    }

                    type = TokenType.TypeDef;
                    goto IL_0644;
                case CodedIndex.MemberRefParent:
                    rid = data >> 3;
                    switch (data & 7)
                    {
                        case 0u:
                            break;
                        case 1u:
                            goto IL_02ef;
                        case 2u:
                            goto IL_02fa;
                        case 3u:
                            goto IL_0305;
                        case 4u:
                            goto IL_0310;
                        default:
                            goto end_IL_0006;
                    }

                    type = TokenType.TypeDef;
                    goto IL_0644;
                case CodedIndex.HasSemantics:
                    {
                        rid = data >> 1;
                        uint num9 = data & 1;
                        uint num10 = num9;
                        if (num10 != 0)
                        {
                            if (num10 != 1)
                            {
                                break;
                            }

                            type = TokenType.Property;
                        }
                        else
                        {
                            type = TokenType.Event;
                        }

                        goto IL_0644;
                    }
                case CodedIndex.MethodDefOrRef:
                    {
                        rid = data >> 1;
                        uint num7 = data & 1;
                        uint num8 = num7;
                        if (num8 != 0)
                        {
                            if (num8 != 1)
                            {
                                break;
                            }

                            type = TokenType.MemberRef;
                        }
                        else
                        {
                            type = TokenType.Method;
                        }

                        goto IL_0644;
                    }
                case CodedIndex.MemberForwarded:
                    {
                        rid = data >> 1;
                        uint num5 = data & 1;
                        uint num6 = num5;
                        if (num6 != 0)
                        {
                            if (num6 != 1)
                            {
                                break;
                            }

                            type = TokenType.Method;
                        }
                        else
                        {
                            type = TokenType.Field;
                        }

                        goto IL_0644;
                    }
                case CodedIndex.Implementation:
                    rid = data >> 2;
                    switch (data & 3)
                    {
                        case 0u:
                            break;
                        case 1u:
                            goto IL_03ec;
                        case 2u:
                            goto IL_03f7;
                        default:
                            goto end_IL_0006;
                    }

                    type = TokenType.File;
                    goto IL_0644;
                case CodedIndex.CustomAttributeType:
                    {
                        rid = data >> 3;
                        uint num3 = data & 7;
                        uint num4 = num3;
                        if (num4 != 2)
                        {
                            if (num4 != 3)
                            {
                                break;
                            }

                            type = TokenType.MemberRef;
                        }
                        else
                        {
                            type = TokenType.Method;
                        }

                        goto IL_0644;
                    }
                case CodedIndex.ResolutionScope:
                    rid = data >> 2;
                    switch (data & 3)
                    {
                        case 0u:
                            break;
                        case 1u:
                            goto IL_046a;
                        case 2u:
                            goto IL_0475;
                        case 3u:
                            goto IL_0480;
                        default:
                            goto end_IL_0006;
                    }

                    type = TokenType.Module;
                    goto IL_0644;
                case CodedIndex.TypeOrMethodDef:
                    {
                        rid = data >> 1;
                        uint num = data & 1;
                        uint num2 = num;
                        if (num2 != 0)
                        {
                            if (num2 != 1)
                            {
                                break;
                            }

                            type = TokenType.Method;
                        }
                        else
                        {
                            type = TokenType.TypeDef;
                        }

                        goto IL_0644;
                    }
                case CodedIndex.HasCustomDebugInformation:
                    {
                        rid = data >> 5;
                        switch (data & 0x1F)
                        {
                            case 0u:
                                break;
                            case 1u:
                                goto IL_0556;
                            case 2u:
                                goto IL_0561;
                            case 3u:
                                goto IL_056c;
                            case 4u:
                                goto IL_0577;
                            case 5u:
                                goto IL_0582;
                            case 6u:
                                goto IL_058d;
                            case 7u:
                                goto IL_0598;
                            case 8u:
                                goto IL_059f;
                            case 9u:
                                goto IL_05aa;
                            case 10u:
                                goto IL_05b5;
                            case 11u:
                                goto IL_05c0;
                            case 12u:
                                goto IL_05c8;
                            case 13u:
                                goto IL_05d0;
                            case 14u:
                                goto IL_05d8;
                            case 15u:
                                goto IL_05e0;
                            case 16u:
                                goto IL_05e8;
                            case 17u:
                                goto IL_05f0;
                            case 18u:
                                goto IL_05f8;
                            case 19u:
                                goto IL_0600;
                            case 20u:
                                goto IL_0608;
                            case 21u:
                                goto IL_0610;
                            case 22u:
                                goto IL_0618;
                            case 23u:
                                goto IL_0620;
                            case 24u:
                                goto IL_0628;
                            case 25u:
                                goto IL_0630;
                            case 26u:
                                goto IL_0638;
                            default:
                                goto end_IL_0006;
                        }

                        type = TokenType.Method;
                        goto IL_0644;
                    }

                    IL_0638:
                    type = TokenType.ImportScope;
                    goto IL_0644;
                    IL_0630:
                    type = TokenType.LocalConstant;
                    goto IL_0644;
                    IL_0628:
                    type = TokenType.LocalVariable;
                    goto IL_0644;
                    IL_0620:
                    type = TokenType.LocalScope;
                    goto IL_0644;
                    IL_0618:
                    type = TokenType.Document;
                    goto IL_0644;
                    IL_0610:
                    type = TokenType.MethodSpec;
                    goto IL_0644;
                    IL_0608:
                    type = TokenType.GenericParamConstraint;
                    goto IL_0644;
                    IL_0600:
                    type = TokenType.GenericParam;
                    goto IL_0644;
                    IL_05f8:
                    type = TokenType.ManifestResource;
                    goto IL_0644;
                    IL_05f0:
                    type = TokenType.ExportedType;
                    goto IL_0644;
                    IL_05e8:
                    type = TokenType.File;
                    goto IL_0644;
                    IL_05e0:
                    type = TokenType.AssemblyRef;
                    goto IL_0644;
                    IL_05d8:
                    type = TokenType.Assembly;
                    goto IL_0644;
                    IL_05d0:
                    type = TokenType.TypeSpec;
                    goto IL_0644;
                    IL_05c8:
                    type = TokenType.ModuleRef;
                    goto IL_0644;
                    IL_05c0:
                    type = TokenType.Signature;
                    goto IL_0644;
                    IL_05b5:
                    type = TokenType.Event;
                    goto IL_0644;
                    IL_05aa:
                    type = TokenType.Property;
                    goto IL_0644;
                    IL_059f:
                    type = TokenType.Permission;
                    goto IL_0644;
                    IL_0598:
                    type = TokenType.Module;
                    goto IL_0644;
                    IL_058d:
                    type = TokenType.MemberRef;
                    goto IL_0644;
                    IL_0582:
                    type = TokenType.InterfaceImpl;
                    goto IL_0644;
                    IL_0577:
                    type = TokenType.Param;
                    goto IL_0644;
                    IL_056c:
                    type = TokenType.TypeDef;
                    goto IL_0644;
                    IL_0561:
                    type = TokenType.TypeRef;
                    goto IL_0644;
                    IL_0556:
                    type = TokenType.Field;
                    goto IL_0644;
                    IL_01f6:
                    type = TokenType.File;
                    goto IL_0644;
                    IL_01eb:
                    type = TokenType.AssemblyRef;
                    goto IL_0644;
                    IL_01d5:
                    type = TokenType.TypeSpec;
                    goto IL_0644;
                    IL_01e0:
                    type = TokenType.Assembly;
                    goto IL_0644;
                    IL_0480:
                    type = TokenType.TypeRef;
                    goto IL_0644;
                    IL_0475:
                    type = TokenType.AssemblyRef;
                    goto IL_0644;
                    IL_046a:
                    type = TokenType.ModuleRef;
                    goto IL_0644;
                    IL_01ca:
                    type = TokenType.ModuleRef;
                    goto IL_0644;
                    IL_01bf:
                    type = TokenType.Signature;
                    goto IL_0644;
                    IL_01a9:
                    type = TokenType.Property;
                    goto IL_0644;
                    IL_01b4:
                    type = TokenType.Event;
                    goto IL_0644;
                    IL_03f7:
                    type = TokenType.ExportedType;
                    goto IL_0644;
                    IL_03ec:
                    type = TokenType.AssemblyRef;
                    goto IL_0644;
                    IL_019e:
                    type = TokenType.Permission;
                    goto IL_0644;
                    IL_0197:
                    type = TokenType.Module;
                    goto IL_0644;
                    IL_0181:
                    type = TokenType.InterfaceImpl;
                    goto IL_0644;
                    IL_018c:
                    type = TokenType.MemberRef;
                    goto IL_0644;
                    IL_0176:
                    type = TokenType.Param;
                    goto IL_0644;
                    IL_0160:
                    type = TokenType.TypeRef;
                    goto IL_0644;
                    IL_016b:
                    type = TokenType.TypeDef;
                    goto IL_0644;
                    IL_0155:
                    type = TokenType.Field;
                    goto IL_0644;
                    IL_0075:
                    type = TokenType.TypeRef;
                    goto IL_0644;
                    IL_0310:
                    type = TokenType.TypeSpec;
                    goto IL_0644;
                    IL_0305:
                    type = TokenType.Method;
                    goto IL_0644;
                    IL_02fa:
                    type = TokenType.ModuleRef;
                    goto IL_0644;
                    IL_02ef:
                    type = TokenType.TypeRef;
                    goto IL_0644;
                    IL_00c8:
                    type = TokenType.Property;
                    goto IL_0644;
                    IL_02aa:
                    type = TokenType.Assembly;
                    goto IL_0644;
                    IL_029f:
                    type = TokenType.Method;
                    goto IL_0644;
                    IL_00bd:
                    type = TokenType.Param;
                    goto IL_0644;
                    IL_0644:
                    return new MetadataToken(type, rid);
                    IL_0080:
                    type = TokenType.TypeSpec;
                    goto IL_0644;
                    IL_022d:
                    type = TokenType.MethodSpec;
                    goto IL_0644;
                    IL_0222:
                    type = TokenType.GenericParamConstraint;
                    goto IL_0644;
                    IL_0217:
                    type = TokenType.GenericParam;
                    goto IL_0644;
                    IL_020c:
                    type = TokenType.ManifestResource;
                    goto IL_0644;
                    IL_0201:
                    type = TokenType.ExportedType;
                    goto IL_0644;
                    end_IL_0006:
                    break;
            }

            return MetadataToken.Zero;
        }

        public static uint CompressMetadataToken(this CodedIndex self, MetadataToken token)
        {
            uint result = 0u;
            if (token.RID == 0)
            {
                return result;
            }

            switch (self)
            {
                case CodedIndex.TypeDefOrRef:
                    result = token.RID << 2;
                    switch (token.TokenType)
                    {
                        case TokenType.TypeDef:
                            return result | 0;
                        case TokenType.TypeRef:
                            return result | 1;
                        case TokenType.TypeSpec:
                            return result | 2;
                    }

                    break;
                case CodedIndex.HasConstant:
                    result = token.RID << 2;
                    switch (token.TokenType)
                    {
                        case TokenType.Field:
                            return result | 0;
                        case TokenType.Param:
                            return result | 1;
                        case TokenType.Property:
                            return result | 2;
                    }

                    break;
                case CodedIndex.HasCustomAttribute:
                    result = token.RID << 5;
                    switch (token.TokenType)
                    {
                        case TokenType.Method:
                            return result | 0;
                        case TokenType.Field:
                            return result | 1;
                        case TokenType.TypeRef:
                            return result | 2;
                        case TokenType.TypeDef:
                            return result | 3;
                        case TokenType.Param:
                            return result | 4;
                        case TokenType.InterfaceImpl:
                            return result | 5;
                        case TokenType.MemberRef:
                            return result | 6;
                        case TokenType.Module:
                            return result | 7;
                        case TokenType.Permission:
                            return result | 8;
                        case TokenType.Property:
                            return result | 9;
                        case TokenType.Event:
                            return result | 0xA;
                        case TokenType.Signature:
                            return result | 0xB;
                        case TokenType.ModuleRef:
                            return result | 0xC;
                        case TokenType.TypeSpec:
                            return result | 0xD;
                        case TokenType.Assembly:
                            return result | 0xE;
                        case TokenType.AssemblyRef:
                            return result | 0xF;
                        case TokenType.File:
                            return result | 0x10;
                        case TokenType.ExportedType:
                            return result | 0x11;
                        case TokenType.ManifestResource:
                            return result | 0x12;
                        case TokenType.GenericParam:
                            return result | 0x13;
                        case TokenType.GenericParamConstraint:
                            return result | 0x14;
                        case TokenType.MethodSpec:
                            return result | 0x15;
                    }

                    break;
                case CodedIndex.HasFieldMarshal:
                    result = token.RID << 1;
                    switch (token.TokenType)
                    {
                        case TokenType.Field:
                            return result | 0;
                        case TokenType.Param:
                            return result | 1;
                    }

                    break;
                case CodedIndex.HasDeclSecurity:
                    result = token.RID << 2;
                    switch (token.TokenType)
                    {
                        case TokenType.TypeDef:
                            return result | 0;
                        case TokenType.Method:
                            return result | 1;
                        case TokenType.Assembly:
                            return result | 2;
                    }

                    break;
                case CodedIndex.MemberRefParent:
                    result = token.RID << 3;
                    switch (token.TokenType)
                    {
                        case TokenType.TypeDef:
                            return result | 0;
                        case TokenType.TypeRef:
                            return result | 1;
                        case TokenType.ModuleRef:
                            return result | 2;
                        case TokenType.Method:
                            return result | 3;
                        case TokenType.TypeSpec:
                            return result | 4;
                    }

                    break;
                case CodedIndex.HasSemantics:
                    result = token.RID << 1;
                    switch (token.TokenType)
                    {
                        case TokenType.Event:
                            return result | 0;
                        case TokenType.Property:
                            return result | 1;
                    }

                    break;
                case CodedIndex.MethodDefOrRef:
                    result = token.RID << 1;
                    switch (token.TokenType)
                    {
                        case TokenType.Method:
                            return result | 0;
                        case TokenType.MemberRef:
                            return result | 1;
                    }

                    break;
                case CodedIndex.MemberForwarded:
                    result = token.RID << 1;
                    switch (token.TokenType)
                    {
                        case TokenType.Field:
                            return result | 0;
                        case TokenType.Method:
                            return result | 1;
                    }

                    break;
                case CodedIndex.Implementation:
                    result = token.RID << 2;
                    switch (token.TokenType)
                    {
                        case TokenType.File:
                            return result | 0;
                        case TokenType.AssemblyRef:
                            return result | 1;
                        case TokenType.ExportedType:
                            return result | 2;
                    }

                    break;
                case CodedIndex.CustomAttributeType:
                    result = token.RID << 3;
                    switch (token.TokenType)
                    {
                        case TokenType.Method:
                            return result | 2;
                        case TokenType.MemberRef:
                            return result | 3;
                    }

                    break;
                case CodedIndex.ResolutionScope:
                    result = token.RID << 2;
                    switch (token.TokenType)
                    {
                        case TokenType.Module:
                            return result | 0;
                        case TokenType.ModuleRef:
                            return result | 1;
                        case TokenType.AssemblyRef:
                            return result | 2;
                        case TokenType.TypeRef:
                            return result | 3;
                    }

                    break;
                case CodedIndex.TypeOrMethodDef:
                    result = token.RID << 1;
                    switch (token.TokenType)
                    {
                        case TokenType.TypeDef:
                            return result | 0;
                        case TokenType.Method:
                            return result | 1;
                    }

                    break;
                case CodedIndex.HasCustomDebugInformation:
                    result = token.RID << 5;
                    switch (token.TokenType)
                    {
                        case TokenType.Method:
                            return result | 0;
                        case TokenType.Field:
                            return result | 1;
                        case TokenType.TypeRef:
                            return result | 2;
                        case TokenType.TypeDef:
                            return result | 3;
                        case TokenType.Param:
                            return result | 4;
                        case TokenType.InterfaceImpl:
                            return result | 5;
                        case TokenType.MemberRef:
                            return result | 6;
                        case TokenType.Module:
                            return result | 7;
                        case TokenType.Permission:
                            return result | 8;
                        case TokenType.Property:
                            return result | 9;
                        case TokenType.Event:
                            return result | 0xA;
                        case TokenType.Signature:
                            return result | 0xB;
                        case TokenType.ModuleRef:
                            return result | 0xC;
                        case TokenType.TypeSpec:
                            return result | 0xD;
                        case TokenType.Assembly:
                            return result | 0xE;
                        case TokenType.AssemblyRef:
                            return result | 0xF;
                        case TokenType.File:
                            return result | 0x10;
                        case TokenType.ExportedType:
                            return result | 0x11;
                        case TokenType.ManifestResource:
                            return result | 0x12;
                        case TokenType.GenericParam:
                            return result | 0x13;
                        case TokenType.GenericParamConstraint:
                            return result | 0x14;
                        case TokenType.MethodSpec:
                            return result | 0x15;
                        case TokenType.Document:
                            return result | 0x16;
                        case TokenType.LocalScope:
                            return result | 0x17;
                        case TokenType.LocalVariable:
                            return result | 0x18;
                        case TokenType.LocalConstant:
                            return result | 0x19;
                        case TokenType.ImportScope:
                            return result | 0x1A;
                    }

                    break;
            }

            throw new ArgumentException();
        }

        public static int GetSize(this CodedIndex self, Func<Table, int> counter)
        {
            int num;
            Table[] array;
            switch (self)
            {
                case CodedIndex.TypeDefOrRef:
                    num = 2;
                    array = new Table[3]
                    {
                    Table.TypeDef,
                    Table.TypeRef,
                    Table.TypeSpec
                    };
                    break;
                case CodedIndex.HasConstant:
                    num = 2;
                    array = new Table[3]
                    {
                    Table.Field,
                    Table.Param,
                    Table.Property
                    };
                    break;
                case CodedIndex.HasCustomAttribute:
                    num = 5;
                    array = new Table[22]
                    {
                    Table.Method,
                    Table.Field,
                    Table.TypeRef,
                    Table.TypeDef,
                    Table.Param,
                    Table.InterfaceImpl,
                    Table.MemberRef,
                    Table.Module,
                    Table.DeclSecurity,
                    Table.Property,
                    Table.Event,
                    Table.StandAloneSig,
                    Table.ModuleRef,
                    Table.TypeSpec,
                    Table.Assembly,
                    Table.AssemblyRef,
                    Table.File,
                    Table.ExportedType,
                    Table.ManifestResource,
                    Table.GenericParam,
                    Table.GenericParamConstraint,
                    Table.MethodSpec
                    };
                    break;
                case CodedIndex.HasFieldMarshal:
                    num = 1;
                    array = new Table[2]
                    {
                    Table.Field,
                    Table.Param
                    };
                    break;
                case CodedIndex.HasDeclSecurity:
                    num = 2;
                    array = new Table[3]
                    {
                    Table.TypeDef,
                    Table.Method,
                    Table.Assembly
                    };
                    break;
                case CodedIndex.MemberRefParent:
                    num = 3;
                    array = new Table[5]
                    {
                    Table.TypeDef,
                    Table.TypeRef,
                    Table.ModuleRef,
                    Table.Method,
                    Table.TypeSpec
                    };
                    break;
                case CodedIndex.HasSemantics:
                    num = 1;
                    array = new Table[2]
                    {
                    Table.Event,
                    Table.Property
                    };
                    break;
                case CodedIndex.MethodDefOrRef:
                    num = 1;
                    array = new Table[2]
                    {
                    Table.Method,
                    Table.MemberRef
                    };
                    break;
                case CodedIndex.MemberForwarded:
                    num = 1;
                    array = new Table[2]
                    {
                    Table.Field,
                    Table.Method
                    };
                    break;
                case CodedIndex.Implementation:
                    num = 2;
                    array = new Table[3]
                    {
                    Table.File,
                    Table.AssemblyRef,
                    Table.ExportedType
                    };
                    break;
                case CodedIndex.CustomAttributeType:
                    num = 3;
                    array = new Table[2]
                    {
                    Table.Method,
                    Table.MemberRef
                    };
                    break;
                case CodedIndex.ResolutionScope:
                    num = 2;
                    array = new Table[4]
                    {
                    Table.Module,
                    Table.ModuleRef,
                    Table.AssemblyRef,
                    Table.TypeRef
                    };
                    break;
                case CodedIndex.TypeOrMethodDef:
                    num = 1;
                    array = new Table[2]
                    {
                    Table.TypeDef,
                    Table.Method
                    };
                    break;
                case CodedIndex.HasCustomDebugInformation:
                    num = 5;
                    array = new Table[27]
                    {
                    Table.Method,
                    Table.Field,
                    Table.TypeRef,
                    Table.TypeDef,
                    Table.Param,
                    Table.InterfaceImpl,
                    Table.MemberRef,
                    Table.Module,
                    Table.DeclSecurity,
                    Table.Property,
                    Table.Event,
                    Table.StandAloneSig,
                    Table.ModuleRef,
                    Table.TypeSpec,
                    Table.Assembly,
                    Table.AssemblyRef,
                    Table.File,
                    Table.ExportedType,
                    Table.ManifestResource,
                    Table.GenericParam,
                    Table.GenericParamConstraint,
                    Table.MethodSpec,
                    Table.Document,
                    Table.LocalScope,
                    Table.LocalVariable,
                    Table.LocalConstant,
                    Table.ImportScope
                    };
                    break;
                default:
                    throw new ArgumentException();
            }

            int num2 = 0;
            for (int i = 0; i < array.Length; i++)
            {
                num2 = Math.Max(counter(array[i]), num2);
            }

            return (num2 < 1 << 16 - num) ? 2 : 4;
        }

        public static Version CheckVersion(Version version)
        {
            if (version == null)
            {
                return ZeroVersion;
            }

            if (version.Build == -1)
            {
                return new Version(version.Major, version.Minor, 0, 0);
            }

            if (version.Revision == -1)
            {
                return new Version(version.Major, version.Minor, version.Build, 0);
            }

            return version;
        }

        public static bool TryGetUniqueDocument(this MethodDebugInformation info, out Document document)
        {
            document = info.SequencePoints[0].Document;
            for (int i = 1; i < info.SequencePoints.Count; i++)
            {
                SequencePoint sequencePoint = info.SequencePoints[i];
                if (sequencePoint.Document != document)
                {
                    return false;
                }
            }

            return true;
        }

        public static void ResolveConstant(this IConstantProvider self, ref object constant, ModuleDefinition module)
        {
            if (module == null)
            {
                constant = NoValue;
                return;
            }

            lock (module.SyncRoot)
            {
                if (constant != NotResolved)
                {
                    return;
                }

                if (module.HasImage())
                {
                    constant = module.Read(self, (IConstantProvider provider, MetadataReader reader) => reader.ReadConstant(provider));
                }
                else
                {
                    constant = NoValue;
                }
            }
        }

        public static bool GetHasCustomAttributes(this ICustomAttributeProvider self, ModuleDefinition module)
        {
            return module.HasImage() && module.Read(self, (ICustomAttributeProvider provider, MetadataReader reader) => reader.HasCustomAttributes(provider));
        }

        public static Collection<CustomAttribute> GetCustomAttributes(this ICustomAttributeProvider self, ref Collection<CustomAttribute> variable, ModuleDefinition module)
        {
            if (module.HasImage())
            {
                return module.Read(ref variable, self, (ICustomAttributeProvider provider, MetadataReader reader) => reader.ReadCustomAttributes(provider));
            }

            Interlocked.CompareExchange(ref variable, new Collection<CustomAttribute>(), null);
            return variable;
        }

        public static bool ContainsGenericParameter(this IGenericInstance self)
        {
            Collection<TypeReference> genericArguments = self.GenericArguments;
            for (int i = 0; i < genericArguments.Count; i++)
            {
                if (genericArguments[i].ContainsGenericParameter)
                {
                    return true;
                }
            }

            return false;
        }

        public static void GenericInstanceFullName(this IGenericInstance self, StringBuilder builder)
        {
            builder.Append("<");
            Collection<TypeReference> genericArguments = self.GenericArguments;
            for (int i = 0; i < genericArguments.Count; i++)
            {
                if (i > 0)
                {
                    builder.Append(",");
                }

                builder.Append(genericArguments[i].FullName);
            }

            builder.Append(">");
        }

        public static bool GetHasGenericParameters(this IGenericParameterProvider self, ModuleDefinition module)
        {
            return module.HasImage() && module.Read(self, (IGenericParameterProvider provider, MetadataReader reader) => reader.HasGenericParameters(provider));
        }

        public static Collection<GenericParameter> GetGenericParameters(this IGenericParameterProvider self, ref Collection<GenericParameter> collection, ModuleDefinition module)
        {
            if (module.HasImage())
            {
                return module.Read(ref collection, self, (IGenericParameterProvider provider, MetadataReader reader) => reader.ReadGenericParameters(provider));
            }

            Interlocked.CompareExchange(ref collection, new GenericParameterCollection(self), null);
            return collection;
        }

        public static bool GetHasMarshalInfo(this IMarshalInfoProvider self, ModuleDefinition module)
        {
            return module.HasImage() && module.Read(self, (IMarshalInfoProvider provider, MetadataReader reader) => reader.HasMarshalInfo(provider));
        }

        public static MarshalInfo GetMarshalInfo(this IMarshalInfoProvider self, ref MarshalInfo variable, ModuleDefinition module)
        {
            return module.HasImage() ? module.Read(ref variable, self, (IMarshalInfoProvider provider, MetadataReader reader) => reader.ReadMarshalInfo(provider)) : null;
        }

        public static bool GetAttributes(this uint self, uint attributes)
        {
            return (self & attributes) != 0;
        }

        public static uint SetAttributes(this uint self, uint attributes, bool value)
        {
            if (value)
            {
                return self | attributes;
            }

            return self & ~attributes;
        }

        public static bool GetMaskedAttributes(this uint self, uint mask, uint attributes)
        {
            return (self & mask) == attributes;
        }

        public static uint SetMaskedAttributes(this uint self, uint mask, uint attributes, bool value)
        {
            if (value)
            {
                self &= ~mask;
                return self | attributes;
            }

            return self & ~(mask & attributes);
        }

        public static bool GetAttributes(this ushort self, ushort attributes)
        {
            return (self & attributes) != 0;
        }

        public static ushort SetAttributes(this ushort self, ushort attributes, bool value)
        {
            if (value)
            {
                return (ushort)(self | attributes);
            }

            return (ushort)(self & ~attributes);
        }

        public static bool GetMaskedAttributes(this ushort self, ushort mask, uint attributes)
        {
            return (self & mask) == attributes;
        }

        public static ushort SetMaskedAttributes(this ushort self, ushort mask, uint attributes, bool value)
        {
            if (value)
            {
                self = (ushort)(self & ~mask);
                return (ushort)(self | attributes);
            }

            return (ushort)(self & ~(mask & attributes));
        }

        public static bool HasImplicitThis(this IMethodSignature self)
        {
            return self.HasThis && !self.ExplicitThis;
        }

        public static void MethodSignatureFullName(this IMethodSignature self, StringBuilder builder)
        {
            builder.Append("(");
            if (self.HasParameters)
            {
                Collection<ParameterDefinition> parameters = self.Parameters;
                for (int i = 0; i < parameters.Count; i++)
                {
                    ParameterDefinition parameterDefinition = parameters[i];
                    if (i > 0)
                    {
                        builder.Append(",");
                    }

                    if (parameterDefinition.ParameterType.IsSentinel)
                    {
                        builder.Append("...,");
                    }

                    builder.Append(parameterDefinition.ParameterType.FullName);
                }
            }

            builder.Append(")");
        }

        public static void CheckModule(ModuleDefinition module)
        {
            if (module == null)
            {
                throw new ArgumentNullException(Argument.module.ToString());
            }
        }

        public static bool TryGetAssemblyNameReference(this ModuleDefinition module, AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference)
        {
            Collection<AssemblyNameReference> assemblyReferences = module.AssemblyReferences;
            for (int i = 0; i < assemblyReferences.Count; i++)
            {
                AssemblyNameReference assemblyNameReference = assemblyReferences[i];
                if (Equals(name_reference, assemblyNameReference))
                {
                    assembly_reference = assemblyNameReference;
                    return true;
                }
            }

            assembly_reference = null;
            return false;
        }

        private static bool Equals(byte[] a, byte[] b)
        {
            if (a == b)
            {
                return true;
            }

            if (a == null)
            {
                return false;
            }

            if (a.Length != b.Length)
            {
                return false;
            }

            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] != b[i])
                {
                    return false;
                }
            }

            return true;
        }

        private static bool Equals<T>(T a, T b) where T : class, IEquatable<T>
        {
            if (a == b)
            {
                return true;
            }

            return a?.Equals(b) ?? false;
        }

        private static bool Equals(AssemblyNameReference a, AssemblyNameReference b)
        {
            if (a == b)
            {
                return true;
            }

            if (a.Name != b.Name)
            {
                return false;
            }

            if (!Equals(a.Version, b.Version))
            {
                return false;
            }

            if (a.Culture != b.Culture)
            {
                return false;
            }

            if (!Equals(a.PublicKeyToken, b.PublicKeyToken))
            {
                return false;
            }

            return true;
        }

        public static ParameterDefinition GetParameter(this Mono.Cecil.Cil.MethodBody self, int index)
        {
            MethodDefinition method = self.method;
            if (method.HasThis)
            {
                if (index == 0)
                {
                    return self.ThisParameter;
                }

                index--;
            }

            Collection<ParameterDefinition> parameters = method.Parameters;
            if (index < 0 || index >= parameters.size)
            {
                return null;
            }

            return parameters[index];
        }

        public static VariableDefinition GetVariable(this Mono.Cecil.Cil.MethodBody self, int index)
        {
            Collection<VariableDefinition> variables = self.Variables;
            if (index < 0 || index >= variables.size)
            {
                return null;
            }

            return variables[index];
        }

        public static bool GetSemantics(this MethodDefinition self, MethodSemanticsAttributes semantics)
        {
            return (self.SemanticsAttributes & semantics) != 0;
        }

        public static void SetSemantics(this MethodDefinition self, MethodSemanticsAttributes semantics, bool value)
        {
            if (value)
            {
                self.SemanticsAttributes |= semantics;
            }
            else
            {
                self.SemanticsAttributes &= (MethodSemanticsAttributes)(ushort)(~(int)semantics);
            }
        }

        public static bool IsVarArg(this IMethodSignature self)
        {
            return self.CallingConvention == MethodCallingConvention.VarArg;
        }

        public static int GetSentinelPosition(this IMethodSignature self)
        {
            if (!self.HasParameters)
            {
                return -1;
            }

            Collection<ParameterDefinition> parameters = self.Parameters;
            for (int i = 0; i < parameters.Count; i++)
            {
                if (parameters[i].ParameterType.IsSentinel)
                {
                    return i;
                }
            }

            return -1;
        }

        public static void CheckName(object name)
        {
            if (name == null)
            {
                throw new ArgumentNullException(Argument.name.ToString());
            }
        }

        public static void CheckName(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullOrEmptyException(Argument.name.ToString());
            }
        }

        public static void CheckFileName(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullOrEmptyException(Argument.fileName.ToString());
            }
        }

        public static void CheckFullName(string fullName)
        {
            if (string.IsNullOrEmpty(fullName))
            {
                throw new ArgumentNullOrEmptyException(Argument.fullName.ToString());
            }
        }

        public static void CheckStream(object stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(Argument.stream.ToString());
            }
        }

        public static void CheckWriteSeek(Stream stream)
        {
            if (!stream.CanWrite || !stream.CanSeek)
            {
                throw new ArgumentException("Stream must be writable and seekable.");
            }
        }

        public static void CheckReadSeek(Stream stream)
        {
            if (!stream.CanRead || !stream.CanSeek)
            {
                throw new ArgumentException("Stream must be readable and seekable.");
            }
        }

        public static void CheckType(object type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(Argument.type.ToString());
            }
        }

        public static void CheckType(object type, Argument argument)
        {
            if (type == null)
            {
                throw new ArgumentNullException(argument.ToString());
            }
        }

        public static void CheckField(object field)
        {
            if (field == null)
            {
                throw new ArgumentNullException(Argument.field.ToString());
            }
        }

        public static void CheckMethod(object method)
        {
            if (method == null)
            {
                throw new ArgumentNullException(Argument.method.ToString());
            }
        }

        public static void CheckParameters(object parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(Argument.parameters.ToString());
            }
        }

        public static uint GetTimestamp()
        {
            return (uint)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
        }

        public static bool HasImage(this ModuleDefinition self)
        {
            return self?.HasImage ?? false;
        }

        public static string GetFileName(this Stream self)
        {
            FileStream fileStream = self as FileStream;
            if (fileStream == null)
            {
                return string.Empty;
            }

            return Path.GetFullPath(fileStream.Name);
        }

        public static TargetRuntime ParseRuntime(this string self)
        {
            if (string.IsNullOrEmpty(self))
            {
                return TargetRuntime.Net_4_0;
            }

            switch (self[1])
            {
                case '1':
                    return (self[3] != '0') ? TargetRuntime.Net_1_1 : TargetRuntime.Net_1_0;
                case '2':
                    return TargetRuntime.Net_2_0;
                default:
                    return TargetRuntime.Net_4_0;
            }
        }

        public static string RuntimeVersionString(this TargetRuntime runtime)
        {
            switch (runtime)
            {
                case TargetRuntime.Net_1_0:
                    return "v1.0.3705";
                case TargetRuntime.Net_1_1:
                    return "v1.1.4322";
                case TargetRuntime.Net_2_0:
                    return "v2.0.50727";
                default:
                    return "v4.0.30319";
            }
        }

        public static bool IsWindowsMetadata(this ModuleDefinition module)
        {
            return module.MetadataKind != MetadataKind.Ecma335;
        }

        public static byte[] ReadAll(this Stream self)
        {
            MemoryStream memoryStream = new MemoryStream((int)self.Length);
            byte[] array = new byte[1024];
            int count;
            while ((count = self.Read(array, 0, array.Length)) != 0)
            {
                memoryStream.Write(array, 0, count);
            }

            return memoryStream.ToArray();
        }

        public static void Read(object o)
        {
        }

        public static bool GetHasSecurityDeclarations(this ISecurityDeclarationProvider self, ModuleDefinition module)
        {
            return module.HasImage() && module.Read(self, (ISecurityDeclarationProvider provider, MetadataReader reader) => reader.HasSecurityDeclarations(provider));
        }

        public static Collection<SecurityDeclaration> GetSecurityDeclarations(this ISecurityDeclarationProvider self, ref Collection<SecurityDeclaration> variable, ModuleDefinition module)
        {
            if (module.HasImage)
            {
                return module.Read(ref variable, self, (ISecurityDeclarationProvider provider, MetadataReader reader) => reader.ReadSecurityDeclarations(provider));
            }

            Interlocked.CompareExchange(ref variable, new Collection<SecurityDeclaration>(), null);
            return variable;
        }

        public static TypeReference GetEnumUnderlyingType(this TypeDefinition self)
        {
            Collection<FieldDefinition> fields = self.Fields;
            for (int i = 0; i < fields.Count; i++)
            {
                FieldDefinition fieldDefinition = fields[i];
                if (!fieldDefinition.IsStatic)
                {
                    return fieldDefinition.FieldType;
                }
            }

            throw new ArgumentException();
        }

        public static TypeDefinition GetNestedType(this TypeDefinition self, string fullname)
        {
            if (!self.HasNestedTypes)
            {
                return null;
            }

            Collection<TypeDefinition> nestedTypes = self.NestedTypes;
            for (int i = 0; i < nestedTypes.Count; i++)
            {
                TypeDefinition typeDefinition = nestedTypes[i];
                if (typeDefinition.TypeFullName() == fullname)
                {
                    return typeDefinition;
                }
            }

            return null;
        }

        public static bool IsPrimitive(this ElementType self)
        {
            ElementType elementType = self;
            ElementType elementType2 = elementType;
            if (elementType2 - 2 <= ElementType.U8 || elementType2 - 24 <= ElementType.Void)
            {
                return true;
            }

            return false;
        }

        public static string TypeFullName(this TypeReference self)
        {
            return string.IsNullOrEmpty(self.Namespace) ? self.Name : (self.Namespace + "." + self.Name);
        }

        public static bool IsTypeOf(this TypeReference self, string @namespace, string name)
        {
            return self.Name == name && self.Namespace == @namespace;
        }

        public static bool IsTypeSpecification(this TypeReference type)
        {
            switch (type.etype)
            {
                case ElementType.Ptr:
                case ElementType.ByRef:
                case ElementType.Var:
                case ElementType.Array:
                case ElementType.GenericInst:
                case ElementType.FnPtr:
                case ElementType.SzArray:
                case ElementType.MVar:
                case ElementType.CModReqD:
                case ElementType.CModOpt:
                case ElementType.Sentinel:
                case ElementType.Pinned:
                    return true;
                default:
                    return false;
            }
        }

        public static TypeDefinition CheckedResolve(this TypeReference self)
        {
            TypeDefinition typeDefinition = self.Resolve();
            if (typeDefinition == null)
            {
                throw new ResolutionException(self);
            }

            return typeDefinition;
        }

        public static bool TryGetCoreLibraryReference(this ModuleDefinition module, out AssemblyNameReference reference)
        {
            Collection<AssemblyNameReference> assemblyReferences = module.AssemblyReferences;
            for (int i = 0; i < assemblyReferences.Count; i++)
            {
                reference = assemblyReferences[i];
                if (IsCoreLibrary(reference))
                {
                    return true;
                }
            }

            reference = null;
            return false;
        }

        public static bool IsCoreLibrary(this ModuleDefinition module)
        {
            if (module.Assembly == null)
            {
                return false;
            }

            if (!IsCoreLibrary(module.Assembly.Name))
            {
                return false;
            }

            if (module.HasImage && module.Read(module, (ModuleDefinition m, MetadataReader reader) => reader.image.GetTableLength(Table.AssemblyRef) > 0))
            {
                return false;
            }

            return true;
        }

        public static void KnownValueType(this TypeReference type)
        {
            if (!type.IsDefinition)
            {
                type.IsValueType = true;
            }
        }

        private static bool IsCoreLibrary(AssemblyNameReference reference)
        {
            string name = reference.Name;
            int result;
            switch (name)
            {
                default:
                    result = ((name == "netstandard") ? 1 : 0);
                    break;
                case "mscorlib":
                case "System.Runtime":
                case "System.Private.CoreLib":
                    result = 1;
                    break;
            }

            return (byte)result != 0;
        }

        public static RSA CreateRSA(this WriterParameters writer_parameters)
        {
            if (writer_parameters.StrongNameKeyBlob != null)
            {
                return CryptoConvert.FromCapiKeyBlob(writer_parameters.StrongNameKeyBlob);
            }

            string key_container;
            byte[] key;
            if (writer_parameters.StrongNameKeyContainer != null)
            {
                key_container = writer_parameters.StrongNameKeyContainer;
            }
            else if (!TryGetKeyContainer(writer_parameters.StrongNameKeyPair, out key, out key_container))
            {
                return CryptoConvert.FromCapiKeyBlob(key);
            }

            CspParameters parameters = new CspParameters
            {
                Flags = CspProviderFlags.UseMachineKeyStore,
                KeyContainerName = key_container,
                KeyNumber = 2
            };
            return new RSACryptoServiceProvider(parameters);
        }

        private static bool TryGetKeyContainer(ISerializable key_pair, out byte[] key, out string key_container)
        {
            SerializationInfo serializationInfo = new SerializationInfo(typeof(StrongNameKeyPair), new FormatterConverter());
            key_pair.GetObjectData(serializationInfo, default(StreamingContext));
            key = (byte[])serializationInfo.GetValue("_keyPairArray", typeof(byte[]));
            key_container = serializationInfo.GetString("_keyPairContainer");
            return key_container != null;
        }

        public static bool IsNullOrEmpty<T>(this T[] self)
        {
            return self == null || self.Length == 0;
        }

        public static bool IsNullOrEmpty<T>(this Collection<T> self)
        {
            return self == null || self.size == 0;
        }

        public static T[] Resize<T>(this T[] self, int length)
        {
            Array.Resize(ref self, length);
            return self;
        }

        public static T[] Add<T>(this T[] self, T item)
        {
            if (self == null)
            {
                self = new T[1]
                {
                    item
                };
                return self;
            }

            self = self.Resize(self.Length + 1);
            self[^1] = item;
            return self;
        }
    }
}